////////////////////////////////////////////////////////////////////////////////
//  Copyright 2011 Adam Kidd
//  
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//  
//    http://www.apache.org/licenses/LICENSE-2.0
//  
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
////////////////////////////////////////////////////////////////////////////////

package com.arcadefoundry.rest.http
{
	import com.arcadefoundry.rest.utils.DateFormatter;
	
	import flash.utils.Dictionary;

	public class HTTPRequestHeaders implements IHTTPRequestHeaders
	{
		//------------------------------------------------
		//
		// Properties
		//
		//------------------------------------------------
		/**
		 * Carriage-Return-Line-Feed - The separator used between headers and
		 * between headers and the content of an HTTP request/response. 
		 */
		private static const CRLF:String = "\r\n";
		
		/**
		 * A dictionary containing all the headers to be used in the request. 
		 */
		private var headers:Dictionary = new Dictionary();
		
		//------------------------------------------------
		//
		// Constructor
		//
		//------------------------------------------------
		public function HTTPRequestHeaders()
		{
			// Empty constructor
		}
		
		//------------------------------------------------
		//
		// Methods
		//
		//------------------------------------------------
		/**
		 * Adds or updates the named header. There is no validation on the
		 * headers used so be careful to ensure they are correct and
		 * properly encoded!
		 *  
		 * @param name The name of the header.
		 * @param value The value of the header.
		 * 
		 */
		public function addHeader(name:String, value:String):void
		{
			headers[name] = value;
		}
		
		/**
		 * Removes the named header.
		 *  
		 * @param name The name of the header.
		 * 
		 */		
		public function removeHeader(name:String):void
		{
			delete headers[name];
		}
		
		//------------------------------------------------
		//
		// Getters & Setters
		//
		//------------------------------------------------
		/**
		 * Sets the accept header for the request. It should include all
		 * MIMETypes that the client can interpret.
		 *  
		 * @param mimeTypes The MIME Types to accept.
		 * 
		 */
		public function setAccept(mimeTypes:Vector.<String>):void
		{
			headers["Accept"] = mimeTypes.join(", ");
		}
		
		/**
		 * Sets the authorization header. The authorization string should
		 * usually be Base64 encoded.
		 *  
		 * @param authString The authorization string.
		 * 
		 */
		public function setAuthorization(authString:String):void
		{
			// TODO: Base64 encoding required?
			headers["Authorization"] = authString;
		}
		
		/**
		 * Sets the content length. This should always match the length of the
		 * content in bytes. It is automatically set in HTTPRequest whenever
		 * the body is modified.
		 *  
		 * @param value The length of the body of the request, in octets.
		 * 
		 */
		public function setContentLength(value:int):void
		{
			headers["Content-Length"] = String(value);
		}
		
		/**
		 * Sets the content type. This should usually be JSON or XML for
		 * communicating with RESTful resources.
		 *  
		 * @param type The MIMEType of the content.
		 * 
		 */
		public function setContentType(type:String):void
		{
			headers["Content-Type"] = type;
		}
		
		/**
		 * Sets the date the message was sent in RFC-822 format.
		 *  
		 * @param date The date the message was sent.
		 * 
		 */
		public function setDate(date:Date):void
		{
			// TODO: Should this be internal and set by the client/socket when
			// sending?
			headers["Date"] = DateFormatter.toRFC822(date);
		}
		
		/**
		 * 
		 * @return A HTTP formatted representation of all the headers.
		 * 
		 */
		public function get content():String
		{
			var output:String = "";
			// Return headers separated by Carriage Return-Line Feed.
			for (var key:Object in headers)
			{
				output += key + ": " + headers[key] + CRLF;
			}
			return output;
		}
		
		/**
		 * 
		 * @return A formatted representation of all the headers.
		 * 
		 */
		public function get toString():String
		{
			var output:String = "";
			// Return headers separated by Line Feed only.
			for (var key:Object in headers)
			{
				output += key + ": " + headers[key] + "\n";
			}
			return output;
		}
	}
}
